package cate.game.role.bag;

import cate.common.table.item.IBagItemTpl;
import cate.common.util.GameResult;
import cate.game.client.msg.MergeMsgSender;
import cate.game.res.MixRes;
import cate.game.res.MixResItem;
import cate.game.res.RewardShow;
import cate.game.role.bag.item.BaseBagItem;

import java.util.HashMap;
import java.util.List;
import java.util.Map;

public interface IBagContainer<E extends BaseBagItem>{
    String getUid();

    String getBagName();

    long count(int tid);

    E getItem(String uid);

    List<E> getList();

    GameResult<Void> addItem(E item, MergeMsgSender sender);

    GameResult<Void> addItem(int tid, long num, MergeMsgSender sender);

    GameResult<Void> addItems(List<E> items, MergeMsgSender sender);

    GameResult<RewardShow> removeItem(String uid, MergeMsgSender sender);

    GameResult<RewardShow> removeItem(int tid, long num, MergeMsgSender sender);

    GameResult<RewardShow> removeItemByUid(String uid, long num, MergeMsgSender sender);

    GameResult<Void> addItemCheck(int tid, long num);

    GameResult<RewardShow> notReallyRemove(String uid, MergeMsgSender sender);

    GameResult<RewardShow> notReallyRemove(int tid, long num, MergeMsgSender sender);

    GameResult<RewardShow> notReallyRemoveItemByUid(String uid, long num, MergeMsgSender sender);

    void forGmAddCapacity();

    int gridEmpty();

    IBagItemTpl getItemTpl(int tid);

    default GameResult<Void> tryAddCapacity(){
        GameResult<Void> r = new GameResult<>();
        return r.fail("无法为此背包扩容");
    }

    /** 不足的格子，如果不足的格子<=0，则说明可以容纳 */
    default int resGridTotal(List<MixResItem> resItemList) {
        VirtualBag vb = new VirtualBag();
        resItemList.forEach(item -> vb.setPile(item.tid(), getPileAvailableOnly(item.tid())));
        int gridNumTotal = 0;
        for(MixResItem resItem : resItemList){
            IBagItemTpl tpl = getItemTpl(resItem.tid());
            gridNumTotal += vb.needGridNum(resItem.tid(),(int)resItem.num,tpl != null ? tpl.getPileMax() : 1);
        }
        return gridNumTotal;
    }

    /** 仅计算该物品可以用来堆叠的数量 */
    default int getPileAvailableOnly(int templateId) {
        IBagItemTpl tpl = getItemTpl(templateId);
        if (tpl == null) {
            return 0;
        }
        int canPile = 0;
        for (BaseBagItem item : this.getList()) {
            if (item.tid == templateId) {
                canPile += tpl.getPileMax() - item.num;
            }
        }
        return canPile;
    }

    final class VirtualBag{
        /** Map<tid, num> */
        private final Map<Integer, Integer> pileMap = new HashMap<>();

        public void setPile(int templateId, int num) {
            Integer pileAvailable = pileMap.get(templateId);
            if (pileAvailable == null) {
                pileAvailable = num;
            } else {
                pileAvailable += num;
            }
            pileMap.put(templateId, pileAvailable);
        }

        /** 不足的格子，如果不足的格子<=0，则说明可以容纳 */
        public long needGridNum(int tid, long num, long pileNum) {
            long needGridNum = 0;
            int pileAvailable = pileMap.getOrDefault(tid, 0);
            long leftNum = num - pileAvailable;
            needGridNum += Math.ceil((double) leftNum / pileNum);
            return needGridNum;
        }
    }
}
